﻿using System.Collections.Generic;
using System.Linq;
using Arquitetura.Architectural.BusinessLogic.Process;
using Arquitetura.Architectural.Model;
using Arquitetura.BusinessLogic.Validation;
using Arquitetura.DataLayer;
using Arquitetura.Model;
using Microsoft.Practices.Unity;

namespace Arquitetura.BusinessLogic.Process
{
    internal class PessoaProcess : ProcessBase, IPessoaProcess
    {
        #region Atributo(s)
        private readonly IAlunoValidation m_alunoValidation;
        private readonly IMaeValidation m_maeValidation;
        private readonly IPessoaRepository m_alunoData;
        #endregion Atributo(s)

        #region Propriedade(s)
        private IAlunoValidation AlunoValidation
        {
            get { return m_alunoValidation ?? base.Resolve<IAlunoValidation>(); }
        }

        private IMaeValidation MaeValidation
        {
            get { return m_maeValidation ?? base.Resolve<IMaeValidation>(); }
        }

        private IPessoaRepository AlunoData
        {
            get { return m_alunoData ?? base.Resolve<IPessoaRepository>(); }
        }
        #endregion Propriedade(s)

        #region Construtor(es)
        public PessoaProcess() :
            this
            (
                new AlunoValidation(new PessoaRepository()),
                new MaeValidation(new PessoaRepository()),
                new PessoaRepository()
            ) { }

        [InjectionConstructor]
        public PessoaProcess(IUnityContainer unityContainer) : base(unityContainer) { }

        public PessoaProcess(
            IAlunoValidation alunoValidation,
            IMaeValidation maeValidation,
            IPessoaRepository alunoData)
        {
            m_alunoValidation = alunoValidation;
            m_maeValidation = maeValidation;
            m_alunoData = alunoData;
        }
        #endregion Construtor(es)

        #region Método(s)
        public Result<IList<Aluno>> ListarAluno()
        {
            Result<IQueryable<Aluno>> resSelect = AlunoData.Select(new string[] { "Mae" });

            if (resSelect.Success)
                return new Result<IList<Aluno>>(resSelect.Returned.ToList());
            else
                return new Result<IList<Aluno>>(resSelect);
        }

        public Result<IList<Aluno>> ListarAluno(Aluno alunoFiltro)
        {
            Result<IQueryable<Aluno>> resSelect = AlunoData.Select(new string[] { "Mae" });

            if (resSelect.Success)
            {
                IQueryable<Aluno> query = resSelect.Returned;
                if (!string.IsNullOrEmpty(alunoFiltro.Nome))
                {
                    query = query.Where(alu => alu.Nome.Contains(alunoFiltro.Nome));
                }

                if (!string.IsNullOrEmpty(alunoFiltro.Sobrenome))
                {
                    query = query.Where(alu => alu.Sobrenome.Contains(alunoFiltro.Sobrenome));
                }

                return new Result<IList<Aluno>>(query.ToList());
            }
            else
                return new Result<IList<Aluno>>(resSelect);
        }

        public Result<IList<Aluno>> ListarAluno(Aluno alunoFiltro, int skipCount, int takeCount, string sortExpression)
        {
            Result<IQueryable<Aluno>> resSelect = AlunoData.Select(new string[] { "Mae" });

            if (resSelect.Success)
            {
                IQueryable<Aluno> query = resSelect.Returned;
                if (!string.IsNullOrEmpty(alunoFiltro.Nome))
                {
                    query = query.Where(alu => alu.Nome.Contains(alunoFiltro.Nome));
                }

                if (!string.IsNullOrEmpty(alunoFiltro.Sobrenome))
                {
                    query = query.Where(alu => alu.Sobrenome.Contains(alunoFiltro.Sobrenome));
                }

                sortExpression = !string.IsNullOrEmpty(sortExpression) ? sortExpression : "Id";
                string[] sortParameters = sortExpression.Split(new char[] { ' ' });
                string sortField = sortParameters.First();
                string sortDirection = sortParameters.Length > 1 ? sortParameters[1] : string.Empty;

                switch (sortField)
                {
                    case "Prontuario":
                        if (!sortDirection.Equals("DESC"))
                        {
                            query = query.OrderBy(alu => alu.Prontuario);
                        }
                        else
                        {
                            query = query.OrderByDescending(alu => alu.Prontuario);
                        }
                        break;

                    case "Nome":
                        if (!sortDirection.Equals("DESC"))
                        {
                            query = query.OrderBy(alu => alu.Nome);
                        }
                        else
                        {
                            query = query.OrderByDescending(alu => alu.Nome);
                        }
                        break;

                    case "Sobrenome":
                        if (!sortDirection.Equals("DESC"))
                        {
                            query = query.OrderBy(alu => alu.Sobrenome);
                        }
                        else
                        {
                            query = query.OrderByDescending(alu => alu.Sobrenome);
                        }
                        break;

                    case "CPF":
                        if (!sortDirection.Equals("DESC"))
                        {
                            query = query.OrderBy(alu => alu.CPF);
                        }
                        else
                        {
                            query = query.OrderByDescending(alu => alu.CPF);
                        }
                        break;

                    case "RG":
                        if (!sortDirection.Equals("DESC"))
                        {
                            query = query.OrderBy(alu => alu.RG);
                        }
                        else
                        {
                            query = query.OrderByDescending(alu => alu.RG);
                        }
                        break;


                    case "Id":
                    default:
                        if (!sortDirection.Equals("DESC"))
                        {
                            query = query.OrderBy(alu => alu.Id);
                        }
                        else
                        {
                            query = query.OrderByDescending(alu => alu.Id);
                        }
                        break;
                }

                query = query.Skip(skipCount);
                query = query.Take(takeCount);

                return new Result<IList<Aluno>>(query.ToList());
            }
            else
                return new Result<IList<Aluno>>(resSelect);
        }

        public Result<int> ContarAluno(Aluno alunoFiltro)
        {
            Result<IQueryable<Aluno>> resSelect = AlunoData.Select();

            if (resSelect.Success)
            {
                IQueryable<Aluno> query = resSelect.Returned;
                if (!string.IsNullOrEmpty(alunoFiltro.Nome))
                {
                    query = query.Where(alu => alu.Nome.Contains(alunoFiltro.Nome));
                }

                if (!string.IsNullOrEmpty(alunoFiltro.Sobrenome))
                {
                    query = query.Where(alu => alu.Sobrenome.Contains(alunoFiltro.Sobrenome));
                }

                return new Result<int>(query.Count());
            }
            else
                return new Result<int>(resSelect);
        }

        public Result<Aluno> ConsultarAluno(Aluno aluno)
        {
            ;
            Result resultado = m_alunoValidation.Setup(aluno, AlunoValidateOperation.Query).Validate();
            if (resultado.Success)
            {
                Result<IQueryable<Aluno>> resSelect = AlunoData.Select(new string[] { "Mae" });
                if (resSelect.Success)
                {
                    IQueryable<Aluno> query = resSelect.Returned;
                    return new Result<Aluno>(query.Where(alu => alu.Id == aluno.Id).First());
                }
                else
                    return new Result<Aluno>(resSelect);
            }
            else
                return new Result<Aluno>(resultado);
        }

        public Result InserirAluno(Aluno aluno)
        {
            Result result = AlunoValidation.Setup(aluno, AlunoValidateOperation.Insert).Validate();

            if (result.Success)
            {
                result = AlunoData.InsertAluno(aluno);
            }

            return result;
        }

        public Result AlterarAluno(Aluno aluno)
        {
            Result resultado = AlunoValidation.Setup(aluno, AlunoValidateOperation.Update).Validate();
            if (resultado.Success)
            {
                resultado = AlunoData.UpdateAluno(aluno);
            }
            return resultado;
        }

        public Result ExcluirAluno(Aluno aluno)
        {
            Result resultado = AlunoValidation.Setup(aluno, AlunoValidateOperation.Delete).Validate();
            if (resultado.Success)
            {
                resultado = AlunoData.DeleteAluno(aluno);
            }
            return resultado;
        }

        public Result InserirMae(Mae mae)
        {
            Result result = MaeValidation.Setup(mae, MaeValidateOperation.Insert).Validate();
            if (result.Success)
            {
                result = AlunoData.InsertMae(mae);
            }
            return result;
        }

        public Result InserirPai(Pai pai)
        {
            return new Result(false);
        }
        #endregion Método(s)
    }
}
